﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using LFSRecord2.Events;
using LFSRecord2.Model;
using Microsoft.Practices.Composite.Presentation.Events;
using System.Windows.Input;
using System.Windows.Data;

namespace LFSRecord2.ViewModel
{
    public class TimelineViewModel : ViewModelBase
    {
        public ObservableCollection<CompLayerBase> AllLayers { get; private set; }
        public ObservableCollection<AudioLayer> AllAudioLayers { get; private set; }

        public readonly DependencyProperty ProjectLengthProperty = DependencyProperty.Register(
          "ProjectLength",
          typeof(double),
          typeof(TimelineViewModel)
        );
        public double ProjectLength
        {
            get { return (double)GetValue(ProjectLengthProperty); }
            set
            {
                SetValue(ProjectLengthProperty, value);
            }
        }

        public static readonly DependencyProperty ProjectFPSProperty = DependencyProperty.Register(
              "ProjectFPS",
              typeof(byte),
              typeof(TimelineViewModel)
            );
        public byte ProjectFPS
        {
            get { return (byte)GetValue(ProjectFPSProperty); }
            set
            {
                SetValue(ProjectFPSProperty, value);
            }
        }

        public static readonly DependencyProperty CurrentFrameProperty = DependencyProperty.Register(
              "CurrentFrame",
              typeof(int),
              typeof(TimelineViewModel),
              new FrameworkPropertyMetadata(new PropertyChangedCallback(OnCurrentFrameChanged))
            );
        public int CurrentFrame
        {
            get { return (int)GetValue(CurrentFrameProperty); }
            set
            {
                SetValue(CurrentFrameProperty, value);
                OnPropertyChanged("CurrentFrame");
            }
        }
        private static void OnCurrentFrameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TimelineViewModel tvm = (TimelineViewModel)d;
            if (tvm.CurrentFrame < 0)
                tvm.SetValue(CurrentFrameProperty, 0);
            else if (tvm.CurrentFrame > tvm.ProjectLength * tvm.ProjectFPS)
                tvm.SetValue(CurrentFrameProperty, (int)(tvm.ProjectLength * tvm.ProjectFPS));
            //else
            //    tvm.OnPropertyChanged("CurrentFrame");
        }

        public TimelineViewModel()
        {
            AllLayers = LfsRecordController.project.Layers;
            AllAudioLayers = LfsRecordController.project.AudioLayers;

            PropertyChanged += OnMyCurrentFrameChanged;
            ServicesFactory.EventService.GetEvent<FrameIndexChangedEvent>().Subscribe(OnCurrentFrameChanged, ThreadOption.UIThread);
            ServicesFactory.EventService.GetEvent<FpsChangedEvent>().Subscribe(OnFPSChanged, ThreadOption.UIThread);

            //SetValue(ProjectLengthProperty, LfsRecordController.project.ProjectLength);
            ProjectLength = LfsRecordController.project.ProjectLength;
            //ProjectFPS = LFSRecordController.project.FPS;
            SetValue(CurrentFrameProperty, CurrentFrame = LfsRecordController.FrameIndex);
            //CurrentFrame = LfsRecordController.FrameIndex;

            Binding myBinding = new Binding("FPS");
            myBinding.Source = LfsRecordController.project;
            BindingOperations.SetBinding(this, TimelineViewModel.ProjectFPSProperty, myBinding);
        }

        private void OnMyCurrentFrameChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "CurrentFrame")
            {
                //Debug.WriteLine("MyCurrent FRameChanged - {0}", CurrentFrame);

                if (CurrentFrame < 0)
                {
                    SetValue(CurrentFrameProperty, 0);
                    //CurrentFrame = 0;
                    //return;
                }
                else if (CurrentFrame > ProjectLength * ProjectFPS)
                {
                    SetValue(CurrentFrameProperty, (int)(ProjectLength * ProjectFPS));
                    //CurrentFrame = (int)(ProjectLength * ProjectFPS);
                    //return;
                }

                ServicesFactory.EventService.GetEvent<FrameIndexChangedEvent>().Publish(
                    new FrameIndexChangedEventArgs() 
                    {
                        Sender = this, 
                        NewFrameIndex = CurrentFrame, 
                        UpdateCurrentValues = true, 
                        UpdateReplayPosition = false
                    });
            }
        }

        private void OnCurrentFrameChanged(FrameIndexChangedEventArgs e)
        {
            if (e.Sender == null || e.Sender.GetType() != typeof(TimelineViewModel))
                SetValue(CurrentFrameProperty, e.NewFrameIndex);
        }

        private void OnFPSChanged(byte fps)
        {
            ProjectFPS = fps;
        }
    }
}
